package cn.lcc.utils.commom.pack;

import cn.lcc.utils.commom.Resp;
import cn.lcc.utils.commom.annotation.Endpoint;
import cn.lcc.utils.commom.annotation.IotField;
import cn.lcc.utils.commom.annotation.IotFieldClass;
import cn.lcc.utils.commom.annotation.Mapping;
import cn.lcc.utils.commom.core.IMessage;
import cn.lcc.utils.commom.core.schema.SchemaService;
import cn.lcc.utils.commom.core.schema.StringSchema;
import cn.lcc.utils.utils.ClassUtils;
import cn.lcc.utils.utils.method.JT808Endpoint;
import com.alibaba.fastjson2.JSON;
import org.apache.commons.lang3.StringUtils;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class ParseUtils {


    public static String hexStr = "33472a393632303435393434302a303039312a44454d4f2c3031303732342c3031303530382c412c33322e3933383336332c4e2c3131352e383639373638332c452c302e33352c3230322e332c302e302c31322c3130302c35342c302c302c30303030303030302c312c302c3436302c302c32323234392c3235323236353535322c3138382c312c2c39433a37463a38313a37333a41353a38422c2d39332c302e30";
    private final static Map<Object, Method> handlerMap = new HashMap<>(64);

    public static void main(String[] args) {
//        HeadersSchema s = transeParse();
//        SchemaService s =
        // 配置请求头

       // 加载 请求头 实体
        HeadersSchema schema = new HeadersSchema();
        heardSchema(schema,hexStr);
        // 加载实体类
       // 加载解析器

       // 加载响应处理接口

    }

    public static List<Field> field_t = new ArrayList<>();

    private static void heardSchema(HeadersSchema schema, String hexStr) {
        HandlerMapping("cn.lcc.utils.utils.method");
        UD_DEMO d = new UD_DEMO();
        SetFields(schema,d,hexStr);
        IMessage s = d;
        System.out.println(s.getClientId());
        SetFields(d,d,hexStr);
        JT808Endpoint jt808Endpoint = new JT808Endpoint();
        Method m =  handlerMap.get(d.getClass().getSimpleName());

        Object[] objects = new Object[m.getParameterTypes().length];
        System.out.println(m.getParameterTypes().length+" "+JSON.toJSONString(m.getParameterTypes()));
        objects[0] = d;
        Resp ds = Resp.success("asdasd");
        objects[1] = ds;
        try {
            m.invoke(jt808Endpoint,objects);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        } catch (InvocationTargetException e) {
            throw new RuntimeException(e);
        }
    }



    public static void HandlerMapping(String endpointPackage) {
        List<Class> endpointClasses = ClassUtils.getClassList(endpointPackage, Endpoint.class);
        for (Class endpointClass : endpointClasses) {
            try {
                Object bean = endpointClass.getDeclaredConstructor((Class[]) null).newInstance((Object[]) null);
                registerHandlers(bean);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
    }

    /**
     * 将Endpoint中被@Mapping标记的方法注册到映射表
     */
    public static synchronized void registerHandlers(Object bean) {
        Class<?> beanClass = bean.getClass();
        Method[] methods = beanClass.getDeclaredMethods();

        for (Method method : methods) {
            Mapping mapping = method.getAnnotation(Mapping.class);

            if (mapping != null) {
                String desc = mapping.desc();
                String[] types = mapping.pointType();
//                handlerMap.put(types[0], method);
//                Handler handler;
//                handler = new SimpleHandler(bean, method, desc, true);
                for (String type : types) {
                    handlerMap.put(type, method);
                }
            }
        }
    }
    private static void SetFields(Object df,Object o, String hexStr) {
        Field[] fields = df.getClass().getDeclaredFields();
        Integer seqno = 0;
        IotFieldClass _class = df.getClass().getAnnotation(IotFieldClass.class);
        String splitMark = null;
        String[] data = null;
        if (_class != null) {
            splitMark = _class.hexValueOptions();
            data = hexStr.split(splitMark);
        }
        for (Field field : fields) {
            try {
                IotField _fieldHex = (IotField) field.getAnnotation(IotField.class);
                if (_fieldHex.hexLength() < 0 || _fieldHex.hexStart() < 0 || StringUtils.isBlank(_fieldHex.parseType())) {
                    continue;
                }
                System.out.println(" field : "+JSON.toJSONString(_fieldHex.version()));
                // 使用哪种解析器 hexString 截取长度
                String parseType = _fieldHex.parseType();
                String hext = "";
                if (StringUtils.isNotBlank(splitMark)) {
                    // 从 data 数组中匹配数据
                    hext = getHexStrData(data,_fieldHex);
                }else{
                    // 从 hexStr 中匹配数据
                    hext = getHexStr(hexStr,_fieldHex);
                }
                SchemaService sd = new StringSchema();
                Object result = sd.handleByte(hext);
                SetField(field,o,hext,result);

            } catch (Exception ex) {
                System.out.println(ex.getLocalizedMessage());
            }
        }
    }

    private static void SetFields(Object o, String hexStr) {
        Field[] fields = o.getClass().getDeclaredFields();
        Integer seqno = 0;
        IotFieldClass _class = o.getClass().getAnnotation(IotFieldClass.class);
        String splitMark = null;
        String[] data = null;
        if (_class != null) {
            splitMark = _class.hexValueOptions();
            data = hexStr.split(splitMark);

        }
        for (Field field : fields) {
            try {
                IotField _fieldHex = (IotField) field.getAnnotation(IotField.class);
                if (_fieldHex.hexLength() < 0 || _fieldHex.hexStart() < 0 || StringUtils.isBlank(_fieldHex.parseType())) {
                    continue;
                }
                // 使用哪种解析器 hexString 截取长度
                String parseType = _fieldHex.parseType();
                String hext = "";
                if (StringUtils.isNotBlank(splitMark)) {
                    // 从 data 数组中匹配数据
                    hext = getHexStrData(data,_fieldHex);
                }else{
                    // 从 hexStr 中匹配数据
                    hext = getHexStr(hexStr,_fieldHex);
                }
                SchemaService sd = new StringSchema();
                Object result = sd.handleByte(hext);
                SetField(field,o,hext,result);

                field_t.add(field);
            } catch (Exception ex) {
                System.out.println(ex.getLocalizedMessage());
            }
        }
    }

    private static String getHexStr(String hexStr, IotField fieldHex) {
        int start = fieldHex.hexStart();
        int hexLen = fieldHex.hexLength();
        String hexVo = fieldHex.hexValueOptions();
        int hexVoi = fieldHex.hexValueIndex();
        StringBuffer buffer = new StringBuffer();
        if(StringUtils.isNotBlank(hexVo)){
            if (StringUtils.isNotBlank(hexVo)){
                return hexStr.split(hexVo)[hexVoi];
            }
        }else if (hexLen>0 && (start+hexLen)<hexStr.length()) {
           buffer.append(hexStr.substring(start,hexLen));
            return buffer.toString();
        }
        return buffer.toString();
    }

    private static String getHexStrData(String[] data, IotField fieldHex) {
        int start = fieldHex.hexStart();
        int hexLen = fieldHex.hexLength();
        StringBuffer buffer = new StringBuffer();
        if (hexLen>0 && (start+hexLen)<=data.length){
            for (int i = start; i < start+hexLen; i++) {
                buffer.append(data[i]);
            }
        }else{
            throw new RuntimeException("字段解析异常 start: "+ start+" len: "+hexLen);
        }
        String hexVo = fieldHex.hexValueOptions();
        int hexVoi = fieldHex.hexValueIndex();
        if (StringUtils.isNotBlank(hexVo)){
            return buffer.toString().split(hexVo)[hexVoi];
        }
        return buffer.toString();
    }

    public static void SetField(Field field, Object o, String hex, Object hexValue) {
        try {

            field.setAccessible(true);
            if (field.getType().getName().equals("java.lang.Double")) {
                field.set(o, Double.valueOf(hexValue+""));
            }
            else {
                field.set(o, hexValue);
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }


}
